package com.timothy.service;

import java.util.ArrayList;
import java.util.List;
import com.timothy.android.util.XMLUtil;
import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.endpoints.stringmessages.DuplexStringMessagesFactory;
import eneter.messaging.endpoints.stringmessages.IDuplexStringMessageSender;
import eneter.messaging.endpoints.stringmessages.IDuplexStringMessagesFactory;
import eneter.messaging.endpoints.stringmessages.StringResponseReceivedEventArgs;
import eneter.messaging.messagingsystems.messagingsystembase.IDuplexOutputChannel;
import eneter.messaging.messagingsystems.messagingsystembase.IMessagingSystemFactory;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
import eneter.net.system.EventHandler;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class CommunicationService extends Service {
	private static final String LOG_TAG = "CommunicationService";
	public static final String PORT = "9999";

	private IDuplexStringMessageSender mySender;
	private Handler myRefresh = new Handler();

	public static class MyRequest {
		public String Text;
	}

	public static class MyResponse {
		public int Length;
	}

	@Override
	public void onCreate() {
		Log.i(LOG_TAG, "CommunicationService.onCreate()...");
		super.onCreate();

		try {
			openConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.i(LOG_TAG, "CommunicationService.onStart()...");
		super.onStart(intent, startId);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(LOG_TAG, "CommunicationService.onStartCommand()...");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		Log.i(LOG_TAG, "CommunicationService.onDestroy()...");
		super.onDestroy();

		mySender.detachDuplexOutputChannel();
	}

	// Binder given to clients
//	private final IBinder mBinder = new CommunicationBinder();


	/**
	 * Class used for the client Binder. Because we know this service always
	 * runs in the same process as its clients, we don't need to deal with IPC.
	 */
	/*public class CommunicationBinder extends Binder {
		public CommunicationService getService() {
			return CommunicationService.this;
		}
	}*/

	/*@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}*/

	private void openConnection() throws Exception {
		Log.i(LOG_TAG, "------------------------CommunicationService.openConnection()...------------------------");

		// Create sender sending MyRequest and as a response receiving
		// MyResponse
		IDuplexStringMessagesFactory aSenderFactory = new DuplexStringMessagesFactory();
		mySender = aSenderFactory.createDuplexStringMessageSender();

		// Subscribe to receive response messages.
		mySender.responseReceived().subscribe(myOnResponseHandler);

		IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
		IDuplexOutputChannel anOutputChannel = aMessaging.createDuplexOutputChannel("tcp://" + MessageSenderUtil.PC_IP + ":" + MessageSenderUtil.PC_PORT + "/");

		Log.i(LOG_TAG, "create connect with server "+MessageSenderUtil.PC_IP + ":" + MessageSenderUtil.PC_PORT);
		
		mySender.attachDuplexOutputChannel(anOutputChannel);
		
		Log.i(LOG_TAG, "------------------------CommunicationService.openConnection() END------------------------");
	}

	private EventHandler<StringResponseReceivedEventArgs> myOnResponseHandler = new EventHandler<StringResponseReceivedEventArgs>() {
		@Override
		public void onEvent(Object sender, StringResponseReceivedEventArgs e) {
			onResponseReceived(sender, e);
		}
	};

	//deal with receive message
	private void onResponseReceived(Object sender,
			final StringResponseReceivedEventArgs e) {
		// Display the result - returned number of characters.
		// Note: Marshal displaying to the correct UI thread.
		Log.i(LOG_TAG,"----------------------onResponseReceived()...----------------------");
		
		myRefresh.post(new Runnable() {
			@Override
			public void run() {
//				receiveMessageString = e.getResponseMessage();
				
//				StringBuffer commond = new StringBuffer();
				String msg = e.getResponseMessage();
				
//				Log.i(LOG_TAG,"CommunicationService.onResponseReceived().run()...");
//				Log.i(LOG_TAG,"Receice Message:"+ msg);
//				while (true) {
//					
////					Log.i(LOG_TAG,"CommunicationService.onResponseReceived().run()..."+ msg);
//					if ( msg != null ) {
//						msg = msg.trim();
//						if( msg.startsWith( COMMAND_START ) ) {
//							commond.setLength(0);
//							commond.append( msg );
//						} else if( COMMAND_END.equalsIgnoreCase(msg) ){
//							commond.append( msg );
//							break;
//						} else {
//							commond.append( msg );
//						}	
//					} else {
//						break;
//					}
//				}
//				
//				processCommand( commond.toString() );
//				Log.i(LOG_TAG,"process message...");
				
				Log.i(LOG_TAG, "Receive from ("+MessageSenderUtil.PC_IP+"):"+msg);
				
				processCommand(msg);
				
			}
		});
		
		Log.i(LOG_TAG,"----------------------onResponseReceived() end----------------------");
	}

	// send message
	public void onSendRequest(String message) {
		// Send the request message. 
		try {
			Log.i(LOG_TAG, "Send to ("+MessageSenderUtil.PC_IP+"):"+message);
			mySender.sendMessage(message);
		} catch (Exception err) {
			EneterTrace.error("Sending the message failed.", err);
		}
	}

	/*public String getReceiveMessageString() {
		return receiveMessageString;
	}*/
	
	public static final int MSG_SEND_SERVER = 0;	
	public static final int MSG_REGISTER_CLIENT = 1;
	public static final int MSG_UNREGISTER_CLIENT = 2;
	public static final int MSG_QUESTION = 3;
	
	public static final int MSG_BASE_STATION = 4;
    public static final int MSG_SHORT_MESSAGE = 5;
    
    public static final int MSG_SLIDE_RESULT = 6;
    public static final int MSG_CLEAR = 7;
    
    public static final int MSG_CONNECT_BASE = 8;
    
    public static final int MSG_STOP_POLLING = 9;
    public static final int MSG_BACK_GROUND = 10;
    
    public static final int MSG_DEMO_CONNECT_SESSION = 11;
    public static final int MSG_DEMO_GET_SESSIONS = 12;
    
    public static final int MSG_DEMO_END_DEMO = 13;
	
//	private static final String COMMAND_START = "<Message";
//	private static final String COMMAND_END = "</Message>";
	
	final Messenger rMessenger = new Messenger(new IncomingHandler());
	List<Messenger> sMessengers = new ArrayList<Messenger>();
	
    @Override
    public IBinder onBind(Intent intent) {
    	return rMessenger.getBinder();
    }
	
	private void processCommand(String command){
		Log.i(LOG_TAG,"----------------------processCommand start----------------------------");
		Object obj = null;
		int objType = 0;
	    String type = XMLUtil.getPropertyValue(command, "Type");
	    String content = XMLUtil.getChildren( command ).get(0);
	    
	    Log.i(LOG_TAG,"command:"+command);
	    Log.i(LOG_TAG,"type:"+type);
	    Log.i(LOG_TAG,"content:"+content);
	    
		if ("CommonQuestion".equals(type)) {
			obj = XMLUtil.getChildren(content).get(0);
			objType = MSG_QUESTION;
		} else if ("SlideResult".equals(type)) {
			obj = XMLUtil.getChildren(content).get(0);
			objType = MSG_SLIDE_RESULT;
		} else if ("Background".equals(type)) {
//			String value = XMLUtil.getChildren(content).get(0);
//			Configuration.background = XMLUtil.getElementValue(value);
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_BACK_GROUND;
		}/* else if ("BackLight".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.backLight = Integer.valueOf(XMLUtil.getElementValue(value));
		} else if ("BubbleBackColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.bubbleBackColor = XMLUtil.getElementValue(value);
		} else if ("ButtonBackColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.buttonBackColor = XMLUtil.getElementValue(value);
		} else if ("BubbleFontColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.bubbleFontColor = XMLUtil.getElementValue(value);
		} else if ("ButtonFontColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.buttonFontColor = XMLUtil.getElementValue(value);
		} else if ("BubbleFontSize".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.bubbleFontSize = Integer.valueOf(XMLUtil.getElementValue(value));
		} else if ("ButtonFontSize".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.buttonFontSize = Integer.valueOf(XMLUtil.getElementValue(value));
			
		}*/else if ("ConnectBase".equalsIgnoreCase(type)) {// Request Connect Base
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_CONNECT_BASE;
		} else if ("BaseStations".equals(type)) {// List Base Stations
			obj = content;
			objType = MSG_BASE_STATION;
		} else if ("ShortMessage".equals(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_SHORT_MESSAGE;
		} else if ("ScreenClear".equals(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_CLEAR;
		} else if ("Deleted".equals(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_CLEAR;
		} else if ("true".equalsIgnoreCase(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_SHORT_MESSAGE;
		} else if ("StopPolling".equalsIgnoreCase(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_STOP_POLLING;
		} else if ("GetSessions".equalsIgnoreCase(type)) {// Request Connect Demo Sessions
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_DEMO_CONNECT_SESSION;
		} else if ("Sessions".equals(type)) {// List Demo Sessions
			obj = content;
			objType = MSG_DEMO_GET_SESSIONS;
		} else if ("EndQuestion".equalsIgnoreCase(type)) {//end demo
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_DEMO_END_DEMO;
		} else {
			Log.i(LOG_TAG, "Message can not be parsed");
		}
			
		if( obj != null ) {	
			for (int i=sMessengers.size()-1; i>=0; i--) {
	             try {
//	            	 Log.i(LOG_TAG,"Send Message Type: "+objType);
//	            	 Log.i(LOG_TAG,"Send Message: "+obj);
	            	 sMessengers.get(i).send( Message.obtain(null, objType, obj) );
	             } catch (RemoteException e) {
	            	 sMessengers.remove(i);
	             }
	        }
		}
		
		Log.i(LOG_TAG,"------------------------processCommand end--------------------------");
	}
	
	class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
        	Log.i(LOG_TAG,"IncomingHandler.handleMessage(): "+msg.what);
            switch (msg.what) {
                case MSG_REGISTER_CLIENT:
                    sMessengers.add(msg.replyTo);
                    Log.i(LOG_TAG,"MSG_REGISTER_CLIENT");
                    break;
                case MSG_UNREGISTER_CLIENT:
                    sMessengers.remove(msg.replyTo);
                    Log.i(LOG_TAG,"MSG_UNREGISTER_CLIENT");
                    break;
                case MSG_SEND_SERVER:
                    Log.i(LOG_TAG,"MSG_SEND_SERVER");
                    onSendRequest((String)msg.obj);
                    break;
            }
        }
    }
	

}